package generator;

import dal.Configuracion;
import dto.Columna;
import dto.Tabla;
import java.io.File;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Vector;

/**
 *
 * @author Jose Carlos Gutierrez
 */
public class GeneradorMySQL extends Generador {

    public GeneradorMySQL(String path) {
        super(path);
    }

    @Override
    public Hashtable<String, String> getColumnas() {
        if (columnas == null) {
            columnas = new Hashtable<String, String>();
            columnas.put("int", "int");
            columnas.put("varchar", "String");
            columnas.put("tinyint", "int");
            columnas.put("decimal", "double");
            columnas.put("char", "String");
            columnas.put("real", "double");
            columnas.put("float", "float");
            columnas.put("date", "Date");
            columnas.put("text", "String");
            columnas.put("bigint", "long");
            columnas.put("smallint", "short");
            columnas.put("bit", "short");
            columnas.put("double precision", "double");
            columnas.put("date", "String");
            columnas.put("datetime", "String");
        }
        return columnas;
    }

    @Override
    protected void generarDTO(Tabla tbl) {
        Escritor objEscritor = new Escritor(path + File.separatorChar
                + "dto" + File.separatorChar + transformarNombre(tbl.getNombreTabla()) + ".java");

        //Titulo de la Clase
        objEscritor.escribir("package dto;");
        objEscritor.escribir("");
        objEscritor.escribir("/**");
        objEscritor.escribir(" *");
        objEscritor.escribir(" * @author Jose Carlos Gutierrez");
        objEscritor.escribir(" */");
        objEscritor.escribir("public class " + transformarNombre(tbl.getNombreTabla()) + "{");
        objEscritor.escribir("");

        //Atributos
        Iterator<Columna> iterador = tbl.getColumnas().iterator();
        while (iterador.hasNext()) {
            Columna col = iterador.next();
            objEscritor.escribir("\tprivate " + col.getJavaType(this) + " " + col.getNombreColumna() + ";");
        }

        //Constructor
        objEscritor.escribir("");
        objEscritor.escribir("\tpublic " + transformarNombre(tbl.getNombreTabla()) + "(){");
        objEscritor.escribir("\t\t;");
        objEscritor.escribir("\t}");
        objEscritor.escribir("");

        //Sets y Gets
        iterador = tbl.getColumnas().iterator();
        while (iterador.hasNext()) {
            Columna col = iterador.next();
            //Set
            objEscritor.escribir("\tpublic void set" + transformarNombre(col.getNombreColumna())
                    + "(" + col.getJavaType(this) + " " + col.getNombreColumna() + "){");
            objEscritor.escribir("\t\tthis." + col.getNombreColumna() + " = " + col.getNombreColumna() + ";");
            objEscritor.escribir("\t}");
            objEscritor.escribir("");
            //Get
            objEscritor.escribir("\tpublic " + col.getJavaType(this) + " get" + transformarNombre(col.getNombreColumna()) + "(){");
            objEscritor.escribir("\t\treturn this." + col.getNombreColumna() + ";");
            objEscritor.escribir("\t}");
            objEscritor.escribir("");
        }
        objEscritor.escribir("}");
        objEscritor.escribir("");
        objEscritor.cerrar();


    }

    @Override
    protected void generarDAO(Tabla tbl) {
        super.generarDAO(tbl);
        Escritor objEscritor = new Escritor(path + File.separatorChar
                + "dao" + File.separatorChar + transformarNombre(tbl.getNombreTabla()) + "DaoMySQL.java");

        //Cabecera de Clase
        objEscritor.escribir("package dao;");
        objEscritor.escribir("");
        objEscritor.escribir("import dal.Conexion;");
        objEscritor.escribir("import dto." + transformarNombre(tbl.getNombreTabla()) + ";");
        objEscritor.escribir("import java.util.Vector;");
        objEscritor.escribir("import java.sql.ResultSet;");
        objEscritor.escribir("");
        objEscritor.escribir("/**");
        objEscritor.escribir(" *");
        objEscritor.escribir(" * @author Jose Carlos Gutierrez");
        objEscritor.escribir(" */");
        objEscritor.escribir("public class " + transformarNombre(tbl.getNombreTabla())
                + "DaoMySQL extends " + transformarNombre(tbl.getNombreTabla()) + "Dao {");
        objEscritor.escribir("");

        //Metodo Update
        objEscritor.escribir("\t@Override");
        objEscritor.escribir("\tpublic void update() throws Exception {");
        objEscritor.escribir("\t\tConexion objConexion = Conexion.getOrCreate();");
        objEscritor.escribir("");
        objEscritor.escribir("\t\tif(objDto.get" + transformarNombre(tbl.getColumnas().elementAt(0).getNombreColumna()) + "() > 0){");
        objEscritor.escribir("\t\t\tStringBuffer query = new StringBuffer(\"UPDATE " + tbl.getNombreTabla() + " SET \");");
        for (int i = 1; i < tbl.getColumnas().size(); i++) {
            Columna columna = tbl.getColumnas().elementAt(i);
            char c = i == tbl.getColumnas().size() - 1 ? ' ' : ',';
            objEscritor.escribir("\t\t\tquery.append(\"" + columna.getNombreColumna() + " = `\" + objDto.get" + transformarNombre(columna.getNombreColumna()) + "() + \"`" + c + "\");");
        }
        objEscritor.escribir("\t\t\tquery.append(\"WHERE " + tbl.getColumnas().elementAt(0).getNombreColumna() + " = `\" + objDto.get" + transformarNombre(tbl.getColumnas().elementAt(0).getNombreColumna()) + "() + \"`\");");
        objEscritor.escribir("\t\t\tint upd = objConexion.ejecutarSimple(query.toString());");
        objEscritor.escribir("\t\t\tif(upd == 0)");
        objEscritor.escribir("\t\t\t\tthrow new Exception(\"El registro no pudo ser actualizado\");");
        objEscritor.escribir("\t\t}");
        objEscritor.escribir("");

        objEscritor.escribir("\t\tif(objDto.get" + transformarNombre(tbl.getColumnas().elementAt(0).getNombreColumna()) + "() == 0){");
        objEscritor.escribir("\t\t\tStringBuffer query = new StringBuffer(\"INSERT INTO " + tbl.getNombreTabla() + " VALUES (\");");
        for (int i = 0; i < tbl.getColumnas().size(); i++) {
            Columna columna = tbl.getColumnas().get(i);
            char c = i == tbl.getColumnas().size() - 1 ? ' ' : ',';
            objEscritor.escribir("\t\t\tquery.append(\"`\" + objDto.get" + transformarNombre(columna.getNombreColumna()) + "() + \"`" + c + "\" );");
        }
        objEscritor.escribir("\t\t\tquery.append(\")\");");
        objEscritor.escribir("\t\t\tint id = objConexion.ejecutarInsert(query.toString());");
        objEscritor.escribir("\t\t\tif(id == 0)");
        objEscritor.escribir("\t\t\t\tthrow new Exception(\"El registro no pudo ser insertado\");");
        objEscritor.escribir("\t\t\telse");
        objEscritor.escribir("\t\t\t\tobjDto.set" + transformarNombre(tbl.getColumnas().get(0).getNombreColumna()) + "(id);");
        objEscritor.escribir("\t\t\tobjConexion.desconectar();");
        objEscritor.escribir("\t\t}");
        objEscritor.escribir("\t}");

        //Metodo Delete
        objEscritor.escribir("\t@Override");
        objEscritor.escribir("\tpublic void delete(){");
        objEscritor.escribir("\t\tConexion objConexion = Conexion.getOrCreate();");
        objEscritor.escribir("\t\tStringBuffer query = new StringBuffer(\"DELETE FROM " + tbl.getNombreTabla() + " \");");
        objEscritor.escribir("\t\tquery.append(\"WHERE " + tbl.getColumnas().get(0).getNombreColumna() +
                " = \" + objDto.get" + transformarNombre(tbl.getColumnas().get(0).getNombreColumna()) + "());");
        objEscritor.escribir("\t\tobjConexion.ejecutarSimple(query.toString());");
        objEscritor.escribir("\t\tobjConexion.desconectar();");
        objEscritor.escribir("\t}");
        objEscritor.escribir("");

        //Metodo Select
        objEscritor.escribir("\t@Override");
        objEscritor.escribir("\tpublic " + transformarNombre(tbl.getNombreTabla()) + " select(int id){");
        objEscritor.escribir("\t\ttry{");
        objEscritor.escribir("\t\t\tConexion objConexion = Conexion.getOrCreate();");
        objEscritor.escribir("\t\t\tString query = \"SELECT * FROM " + tbl.getNombreTabla() + " WHERE " + tbl.getColumnas().get(0).getNombreColumna() + " = \" + id;");
        objEscritor.escribir("\t\t\tResultSet objResultSet = objConexion.ejecutar(query);");
        objEscritor.escribir("\t\t\tif(objResultSet.next()){");
        objEscritor.escribir("\t\t\t\t" + transformarNombre(tbl.getNombreTabla()) + " obj = new " + transformarNombre(tbl.getNombreTabla()) + "();");
        Iterator<Columna> objIterador = tbl.getColumnas().iterator();
        while(objIterador.hasNext()){
            Columna columna = objIterador.next();
            objEscritor.escribir("\t\t\t\t" + columna.getJavaType(this) + " _" + columna.getNombreColumna() + " = objResultSet.get" +
                    transformarNombre(columna.getJavaType(this)) + "(\"" + columna.getNombreColumna() + "\");" );
            objEscritor.escribir("\t\t\t\tobj.set" + transformarNombre(columna.getNombreColumna()) + "(_" + columna.getNombreColumna() + ");");
            objEscritor.escribir("\t\t\t\t");
        }
        objEscritor.escribir("\t\t\t\treturn obj;");
        objEscritor.escribir("\t\t\t}");
        objEscritor.escribir("\t\t}catch(Exception ex){");
        objEscritor.escribir("\t\t\t;");
        objEscritor.escribir("\t\t}");
        objEscritor.escribir("\t\treturn null;");
        objEscritor.escribir("\t}");
        objEscritor.escribir("");

        //Metodo selectTodos
        objEscritor.escribir("\t@Override");
        objEscritor.escribir("\tpublic Vector<" + transformarNombre(tbl.getNombreTabla()) + "> selectTodos(){");
        objEscritor.escribir("\t\tVector<" + transformarNombre(tbl.getNombreTabla()) + ">  registros = new Vector<" + transformarNombre(tbl.getNombreTabla()) + ">();" );
        objEscritor.escribir("\t\ttry{");
        objEscritor.escribir("\t\t\tConexion objConexion = Conexion.getOrCreate();");
        objEscritor.escribir("\t\t\tString query = \"SELECT * FROM " + tbl.getNombreTabla() + "\";");
        objEscritor.escribir("\t\t\tResultSet objResultSet = objConexion.ejecutar(query);");
        objEscritor.escribir("\t\t\twhile(objResultSet.next()){");
        objEscritor.escribir("\t\t\t\t" + transformarNombre(tbl.getNombreTabla()) + " obj = new " + transformarNombre(tbl.getNombreTabla()) + "();");
        objIterador = tbl.getColumnas().iterator();
        while(objIterador.hasNext()){
            Columna columna = objIterador.next();
            objEscritor.escribir("\t\t\t\t" + columna.getJavaType(this) + " _" + columna.getNombreColumna() + " = objResultSet.get" +
                    transformarNombre(columna.getJavaType(this)) + "(\"" + columna.getNombreColumna() + "\");" );
            objEscritor.escribir("\t\t\t\tobj.set" + transformarNombre(columna.getNombreColumna()) + "(_" + columna.getNombreColumna() + ");");
            
            objEscritor.escribir("\t\t\t\t");
        }
        objEscritor.escribir("\t\t\t\tregistros.addElement(obj);");
        objEscritor.escribir("\t\t\t}");
        objEscritor.escribir("\t\t}catch(Exception ex){");
        objEscritor.escribir("\t\t\t;");
        objEscritor.escribir("\t\t}");
        objEscritor.escribir("\t\treturn registros;");
        objEscritor.escribir("\t}");
        objEscritor.escribir("");
        objEscritor.escribir("}");
        objEscritor.escribir("");
        objEscritor.cerrar();
    }

    @Override
    protected void generarFactory(Vector<Tabla> tablas) {
        super.generarFactory(tablas);
        Escritor objEscritor = new Escritor(path + File.separatorChar + "factory" + File.separatorChar + "FactoryDaoMySQL.java");
        objEscritor.escribir("package factory;");
        objEscritor.escribir("");
        objEscritor.escribir("import dal.Configuracion;");
        objEscritor.escribir("import dao.*;");
        objEscritor.escribir("");
        objEscritor.escribir("/**");
        objEscritor.escribir(" *");
        objEscritor.escribir(" * @author Jose Carlos Gutierrez");
        objEscritor.escribir(" */");
        objEscritor.escribir("public class FactoryDaoMySQL extends FactoryDao{");
        objEscritor.escribir("");
        objEscritor.escribir("\tprivate FactoryDaoMySQL(){");
        objEscritor.escribir("\t\t;");
        objEscritor.escribir("\t}");
        objEscritor.escribir("");
        objEscritor.escribir("\tpublic static FactoryDao getFactoryInstance(){");
        objEscritor.escribir("\t\tif(instancia==null)");
        objEscritor.escribir("\t\t\tinstancia = new FactoryDaoMySQL();");
        objEscritor.escribir("\t\treturn instancia;");
        objEscritor.escribir("\t}");
        objEscritor.escribir("");

        Iterator<Tabla> iterador = tablas.iterator();
        while (iterador.hasNext()) {
            Tabla objTabla = iterador.next();
            objEscritor.escribir("\t@Override");
            objEscritor.escribir("\tpublic "
                    + transformarNombre(objTabla.getNombreTabla())
                    + "Dao getNew"
                    + transformarNombre(objTabla.getNombreTabla())
                    + "Dao(){");
            objEscritor.escribir("\t\treturn new " + transformarNombre(objTabla.getNombreTabla()) + "DaoMySQL();");
            objEscritor.escribir("\t}");
            objEscritor.escribir("");
        }

        objEscritor.escribir("}");
        objEscritor.escribir("");
        objEscritor.cerrar();
    }

    public static void main(String[] args) {
        Configuracion config = Configuracion.getConfiguracion();
        config.setDbEngine("MySQL");
        config.setDbHost("localhost");
        config.setDbInstace("");
        config.setDbUser("root");
        config.setDbName("database");
        config.setDbPort("1236");
        config.setDbPassword("root");
        Generador gen = new GeneradorMySQL("C:\\Users\\joseco\\Desktop");
        gen.generarConfiguracion();
        gen.generarDAL();
    }

    @Override
    public void generarFactoryConstructor(Escritor objEscritor) {
        objEscritor.escribir("\t\t\tif(config.getDbEngine().equals(\"MySQL\"));");
        objEscritor.escribir("\t\t\t\tinstancia = FactoryDaoMySQL.getFactoryInstance();");
    }
}
